package com.example.demo.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.demo.bean.PageRes;
import com.example.demo.bean.log.SysLoginLogDO;
import com.example.demo.bean.sysrole.SysRoleDO;
import com.example.demo.bean.sysuser.SysUserDO;
import com.example.demo.bean.sysuser.SysUserRoleDO;
import com.example.demo.config.MyConfig;
import com.example.demo.context.SysContext;
import com.example.demo.dto.sysuser.*;
import com.example.demo.exception.OtherException;
import com.example.demo.mapper.sysuser.SysUserMapper;
import com.example.demo.service.ISysLoginLogService;
import com.example.demo.service.ISysRoleService;
import com.example.demo.service.ISysUserRoleService;
import com.example.demo.service.ISysUserService;
import com.example.demo.util.*;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUserDO> implements ISysUserService {

    @Resource
    private SysUserMapper sysUserMapper;
    @Resource
    private PasswordUtil passwordUtil;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private ISysUserRoleService sysUserRoleService;

    @Resource
    private ISysRoleService sysRoleService;

    @Resource
    private ISysLoginLogService sysLoginLogService;

    /**
     * 登录
     *
     * @param loginReqVO
     * @return
     */
    @Override
    public LoginRepVO login(LoginReqVO loginReqVO) {
        SysUserDO validResult = loginBeforeCheck(loginReqVO);
        String token = JwtUtil.generateToken(validResult.getUserId());
        redisUtil.set(token, validResult.getUserId().toString(), MyConfig.getExpireTime());
        return new LoginRepVO()
                .setAccount(validResult.getUserName())
                .setToken(token)
                .setAvatar(validResult.getAvatar());
    }

    // 登录前校验
    public SysUserDO loginBeforeCheck(LoginReqVO loginReqVO) {
        SysLoginLogDO sysLoginLogDO = new SysLoginLogDO()
                .setUserName(loginReqVO.getUserName())
                .setIpAddr(IpUtils.getIpAddr())
                .setLoginLocation(AddressUtils.getRealAddressByIP(IpUtils.getIpAddr()))
                .setBrowser(ServletUtils.getBrowser())
                .setOs(ServletUtils.getOS())
                .setLoginTime(DateUtil.date());
        SysUserDO validExist = sysUserMapper.selectOne(new QueryWrapper<SysUserDO>().eq("user_name", loginReqVO.getUserName()));
        // 校验用户是否存在
        if (ObjectUtil.isNull(validExist)) {
            SysContext.clean();
            sysLoginLogService.addSysLoginLog(sysLoginLogDO.setStatus(1).setMsg("用户名或密码错误"));
            throw new OtherException("用户名或密码错误");
        } else {
            if (validExist.getStatus() == 1) {
                SysContext.clean();
                sysLoginLogService.addSysLoginLog(sysLoginLogDO.setStatus(1).setMsg("用户已被禁用"));
                throw new OtherException("用户已被禁用");
            } else {
                if (!PasswordUtil.match(loginReqVO.getPassword(), validExist.getPassword())) {
                    SysContext.clean();
                    sysLoginLogService.addSysLoginLog(sysLoginLogDO.setStatus(1).setMsg("用户名或密码错误"));
                    throw new OtherException("用户名或密码错误");
                } else {
                    SysContext.set(validExist.getUserId().toString());
                    sysLoginLogService.addSysLoginLog(sysLoginLogDO.setStatus(0).setMsg("登录成功"));
                    return validExist;
                }
            }
        }
    }

    @Override
    public PageRes<SysUserDO> list(SysUserPageReqVO sysUserPageReqVO) {
        return sysUserPageReqVO.getPageSize() == -1
                ? sysUserMapper.selectNotPage(sysUserPageReqVO)
                : sysUserMapper.selectPage(sysUserPageReqVO);
    }

    @Override
    @Transactional
    public int addSysUser(SysUserDO sysUserDO) {
        validateUserNameExists(sysUserDO.getUserName(), null);
        int insert = sysUserMapper.insert(sysUserDO);
        if (insert > 0) {
            SysUserRoleDO sysUserRoleDO = new SysUserRoleDO().setUserId(sysUserDO.getUserId()).setRoleId(sysUserDO.getRoleId());
            return sysUserRoleService.addSysUserRole(sysUserRoleDO);
        } else {
            return -1;
        }
    }

    @Override
    @Transactional
    public int updateSysUser(SysUserDO sysUserDO) {
        validateSysUserExists(sysUserDO.getUserId());
        validateUserNameExists(sysUserDO.getUserName(), sysUserDO);
        if (sysUserDO.getRoleId() != null) {
            SysUserRoleDO sysUserRoleDO = new SysUserRoleDO().setUserId(sysUserDO.getUserId()).setRoleId(sysUserDO.getRoleId());
            sysUserRoleService.addSysUserRole(sysUserRoleDO);
        }
        return sysUserMapper.updateById(sysUserDO);
    }

    @Override
    @Transactional
    public int deleteSysUser(Long userIds) {
        validateSysUserExists(userIds);
        int delete = sysUserMapper.deleteById(userIds);
        if (delete > 0) {
            return sysUserRoleService.deleteUserRoleByUserId(userIds);
        } else {
            return -1;
        }
    }

    @Override
    public SysUserDO getSysUser(SysUserDO sysUserDO) {
        validateSysUserExists(sysUserDO.getUserId());
        SysUserDO userInfo = sysUserMapper.selectById(sysUserDO.getUserId());
        if (userInfo.getIsRoot() != 1) {
            SysUserRoleDO sysUserRole = sysUserRoleService.getSysUserRole(sysUserDO.getUserId());
            SysRoleDO sysRole = sysRoleService.getSysRole(new SysRoleDO().setId(sysUserRole.getRoleId()));
            userInfo.setRoleId(sysUserRole.getRoleId()).setRoleName(sysRole.getRoleName());
        }
        return userInfo;
    }

    @Override
    public int changeSysUserStatus(SysUserDO sysUserDO) {
        validateSysUserExists(sysUserDO.getUserId());
        return sysUserMapper.updateById(sysUserDO);
    }

    @Override
    public int resetPwd(SysUserDO sysUserDO) {
        validateSysUserExists(sysUserDO.getUserId());
        return sysUserMapper.updateById(sysUserDO);
    }

    @Override
    public int modifyPwd(ModifyPwdReqVO modifyPwdReqVO) {
        Long currentUserId = Long.parseLong(SysContext.get());
        validateSysUserExists(currentUserId);
        SysUserDO exist = sysUserMapper.selectById(currentUserId);
        // 校验密码
        if (!PasswordUtil.match(modifyPwdReqVO.getOldPassword(), exist.getPassword())) {
            throw new OtherException("旧密码错误");
        } else {
            SysUserDO update = new SysUserDO().setUserId(currentUserId).setPassword(modifyPwdReqVO.getNewPassword());
            return sysUserMapper.updateById(update);
        }
    }

    @Override
    public int modifyAvatar(ModifyAvatarReqVO modifyAvatarReqVO) {
        Long currentUserId = Long.parseLong(SysContext.get());
        validateSysUserExists(currentUserId);
        SysUserDO updateAvatar = new SysUserDO().setUserId(currentUserId).setAvatar(modifyAvatarReqVO.getAvatar());
        return sysUserMapper.updateById(updateAvatar);
    }

    private void validateSysUserExists(Long userId) {
        if (sysUserMapper.selectById(userId) == null) {
            throw new OtherException("用户不存在");
        }
    }

    private void validateUserNameExists(String userName, SysUserDO oldInfo) {
        QueryWrapper<SysUserDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_name", userName);
        if (oldInfo != null) {
            queryWrapper.ne("user_id", oldInfo.getUserId());
        }
        SysUserDO exist = sysUserMapper.selectOne(queryWrapper);
        if (exist != null) {
            throw new OtherException("用户名已存在");
        }
    }
}
